#include "hisurfaceview.h"

#include <cstdint>
#include <chrono>
#include <functional>

#include "util/log_util.h"

typedef std::uint8_t byte_t;

typedef struct {
  byte_t r;
  byte_t g;
  byte_t b;
  byte_t a;
} rgba_t;

HiSurfaceView::HiSurfaceView(ANativeWindow *window) : is_drawing_(false) {
  LOGI(__func__);
  window_ = window;
}

HiSurfaceView::~HiSurfaceView() {
  LOGI(__func__);
  StopDrawing();
  ReleaseWindow();
}

void HiSurfaceView::OnWindowChanged(ANativeWindow *window,
    int format, int width, int height) {
  LOGI("%s, format: %d, width: %d, height: %d", __func__,
      format, width, height);
  if (window == nullptr) {
    LOGW("%s, window is null, unexpected", __func__);
    return;
  }
  if (window_ != window) {
    ReleaseWindow();
    window_ = window;
  }
  if (format != WINDOW_FORMAT_RGBA_8888) {
    LOGW("%s, window format change to RGBA_8888", __func__);
    ANativeWindow_setBuffersGeometry(window_, width, height,
        WINDOW_FORMAT_RGBA_8888);
  }
  // auto format = ANativeWindow_getFormat(window_);

  StartDrawing();
}

void HiSurfaceView::StartDrawing() {
  LOGI(__func__);
  if (is_drawing_) return;
  is_drawing_ = true;
  draw_thread_ = std::thread(std::bind(&HiSurfaceView::Run, this));
}

void HiSurfaceView::StopDrawing() {
  LOGI(__func__);
  if (!is_drawing_) return;
  is_drawing_ = false;
  if (draw_thread_.joinable()) {
    draw_thread_.join();
  }
}

void HiSurfaceView::Run() {
  LOGI("%s, beg", __func__);
  ANativeWindow_Buffer buffer;
  ARect rect;
  while (is_drawing_) {
    if (ANativeWindow_lock(window_, &buffer, &rect) == 0) {
      OnDraw(&buffer, &rect);
      ANativeWindow_unlockAndPost(window_);
    } else {
      LOGW("%s, window lock fail", __func__);
    }
  }
  LOGI("%s, end", __func__);
}

void HiSurfaceView::OnDraw(ANativeWindow_Buffer *buffer, ARect *rect) {
  //  LOGI("%s, buffer format: %d, width: %d, height: %d, stride: %d",
  //      __func__, buffer->format, buffer->width, buffer->height, buffer->stride);
  //  LOGI("%s, rect left: %d, top: %d, right: %d, bottom: %d",
  //      __func__, rect->left, rect->top, rect->right, rect->bottom);

  static int32_t draw_count = 0;
  static int32_t cell_size = 10;

  auto rgba_pixels = static_cast<rgba_t*>(buffer->bits);
  for (int32_t row = 0; row < buffer->height; row++) {
    bool row_red = ((row + draw_count) % cell_size == 0);
    for (int32_t col = 0; col < buffer->width; col++) {
      bool col_red = ((col + draw_count) % cell_size == 0);
      auto rgba_pixel = rgba_pixels + col;
      if (row_red || col_red) {
        rgba_pixel->r = 0xff;
        rgba_pixel->g = 0x00;
        rgba_pixel->b = 0x00;
      } else {
        rgba_pixel->r = 0xff;
        rgba_pixel->g = 0xff;
        rgba_pixel->b = 0xff;
      }
      rgba_pixel->a = 0xff;
    }
    rgba_pixels += buffer->stride;
  }

  ++draw_count;
}

void HiSurfaceView::ReleaseWindow() {
  if (window_)
    ANativeWindow_release(window_);
  window_ = nullptr;
}
